<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=2">
<meta name="theme-color" content="#222">
<meta name="generator" content="Hexo 4.0.0">
  <link rel="apple-touch-icon" sizes="180x180" href="/images/apple-touch-icon-next.png">
  <link rel="icon" type="image/png" sizes="32x32" href="/images/favicon-32x32-next.png">
  <link rel="icon" type="image/png" sizes="16x16" href="/images/favicon-16x16-next.png">
  <link rel="mask-icon" href="/images/logo.svg" color="#222">
  <link rel="alternate" href="/atom.xml" title="dy2903的博客" type="application/atom+xml">

<link rel="stylesheet" href="/css/main.css">


<link rel="stylesheet" href="/lib/font-awesome/css/font-awesome.min.css">


<script id="hexo-configurations">
  var NexT = window.NexT || {};
  var CONFIG = {
    root: '/',
    scheme: 'Pisces',
    version: '7.5.0',
    exturl: false,
    sidebar: {"position":"left","display":"post","offset":12,"onmobile":false},
    copycode: {"enable":false,"show_result":false,"style":null},
    back2top: {"enable":true,"sidebar":false,"scrollpercent":false},
    bookmark: {"enable":false,"color":"#222","save":"auto"},
    fancybox: false,
    mediumzoom: false,
    lazyload: false,
    pangu: false,
    algolia: {
      appID: '',
      apiKey: '',
      indexName: '',
      hits: {"per_page":10},
      labels: {"input_placeholder":"Search for Posts","hits_empty":"We didn't find any results for the search: ${query}","hits_stats":"${hits} results found in ${time} ms"}
    },
    localsearch: {"enable":false,"trigger":"auto","top_n_per_article":1,"unescape":false,"preload":false},
    path: '',
    motion: {"enable":true,"async":false,"transition":{"post_block":"fadeIn","post_header":"slideDownIn","post_body":"slideDownIn","coll_header":"slideLeftIn","sidebar":"slideUpIn"}},
    translation: {
      copy_button: 'Copy',
      copy_success: 'Copied',
      copy_failure: 'Copy failed'
    },
    sidebarPadding: 40
  };
</script>

  <meta name="description" content="存储其实就是一台主机，上面也运行着各种各样的应用程序，可以在原本的裸数据之上实现更高级的功能，实现更多的附加值。现在的高端存储越来越开发，比如EMC 的 V-MAX，高端存储也用普通的x86了。 存储系统有两大功能：数据存储和数据管理。  数据存储：控制器、磁盘、HBA卡等，主要是提供裸数据存储服务。  数据管理：分层、快照、克隆等高级功能。又可把数据管理部分分为对数据的前处理和后处理  前处理：">
<meta property="og:type" content="article">
<meta property="og:title" content="大话存储，学习笔记（18章），数据前处理和后处理">
<meta property="og:url" content="https:&#x2F;&#x2F;duyang2903.gitee.io&#x2F;2019&#x2F;11&#x2F;15&#x2F;%E5%A4%A7%E8%AF%9D%E5%AD%98%E5%82%A8%EF%BC%8C%E5%AD%A6%E4%B9%A0%E7%AC%94%E8%AE%B0%EF%BC%8818%E7%AB%A0%EF%BC%89%EF%BC%8C%E6%95%B0%E6%8D%AE%E5%89%8D%E5%A4%84%E7%90%86%E5%92%8C%E5%90%8E%E5%A4%84%E7%90%86&#x2F;index.html">
<meta property="og:site_name" content="dy2903的博客">
<meta property="og:description" content="存储其实就是一台主机，上面也运行着各种各样的应用程序，可以在原本的裸数据之上实现更高级的功能，实现更多的附加值。现在的高端存储越来越开发，比如EMC 的 V-MAX，高端存储也用普通的x86了。 存储系统有两大功能：数据存储和数据管理。  数据存储：控制器、磁盘、HBA卡等，主要是提供裸数据存储服务。  数据管理：分层、快照、克隆等高级功能。又可把数据管理部分分为对数据的前处理和后处理  前处理：">
<meta property="og:locale" content="en">
<meta property="og:image" content="http:&#x2F;&#x2F;upload-images.jianshu.io&#x2F;upload_images&#x2F;1323506-23417ce5aa268c69.png?imageMogr2&#x2F;auto-orient&#x2F;strip%7CimageView2&#x2F;2&#x2F;w&#x2F;1240">
<meta property="og:image" content="http:&#x2F;&#x2F;upload-images.jianshu.io&#x2F;upload_images&#x2F;1323506-bcc64eec94fa3921.png?imageMogr2&#x2F;auto-orient&#x2F;strip%7CimageView2&#x2F;2&#x2F;w&#x2F;1240">
<meta property="og:image" content="http:&#x2F;&#x2F;upload-images.jianshu.io&#x2F;upload_images&#x2F;1323506-9efd2a107ec96778.png?imageMogr2&#x2F;auto-orient&#x2F;strip%7CimageView2&#x2F;2&#x2F;w&#x2F;1240">
<meta property="og:image" content="http:&#x2F;&#x2F;upload-images.jianshu.io&#x2F;upload_images&#x2F;1323506-29bc778c574a6338.png?imageMogr2&#x2F;auto-orient&#x2F;strip%7CimageView2&#x2F;2&#x2F;w&#x2F;1240">
<meta property="og:image" content="http:&#x2F;&#x2F;upload-images.jianshu.io&#x2F;upload_images&#x2F;1323506-b64d1f5a73ea0c04.png?imageMogr2&#x2F;auto-orient&#x2F;strip%7CimageView2&#x2F;2&#x2F;w&#x2F;1240">
<meta property="og:image" content="http:&#x2F;&#x2F;upload-images.jianshu.io&#x2F;upload_images&#x2F;1323506-ad949c38a020a603.png?imageMogr2&#x2F;auto-orient&#x2F;strip%7CimageView2&#x2F;2&#x2F;w&#x2F;1240">
<meta property="og:image" content="http:&#x2F;&#x2F;upload-images.jianshu.io&#x2F;upload_images&#x2F;1323506-040f7a2cbccea364.png?imageMogr2&#x2F;auto-orient&#x2F;strip%7CimageView2&#x2F;2&#x2F;w&#x2F;1240">
<meta property="og:image" content="http:&#x2F;&#x2F;upload-images.jianshu.io&#x2F;upload_images&#x2F;1323506-f1f66c109e142cf8.png?imageMogr2&#x2F;auto-orient&#x2F;strip%7CimageView2&#x2F;2&#x2F;w&#x2F;1240">
<meta property="og:image" content="http:&#x2F;&#x2F;upload-images.jianshu.io&#x2F;upload_images&#x2F;1323506-6f143cb79e866a4d.png?imageMogr2&#x2F;auto-orient&#x2F;strip%7CimageView2&#x2F;2&#x2F;w&#x2F;1240">
<meta property="og:image" content="http:&#x2F;&#x2F;upload-images.jianshu.io&#x2F;upload_images&#x2F;1323506-b26816b8afd22491.png?imageMogr2&#x2F;auto-orient&#x2F;strip%7CimageView2&#x2F;2&#x2F;w&#x2F;1240">
<meta property="og:image" content="http:&#x2F;&#x2F;upload-images.jianshu.io&#x2F;upload_images&#x2F;1323506-2177aaa5e479ffec.png?imageMogr2&#x2F;auto-orient&#x2F;strip%7CimageView2&#x2F;2&#x2F;w&#x2F;1240">
<meta property="og:image" content="http:&#x2F;&#x2F;upload-images.jianshu.io&#x2F;upload_images&#x2F;1323506-f874996a7aa24c5c.png?imageMogr2&#x2F;auto-orient&#x2F;strip%7CimageView2&#x2F;2&#x2F;w&#x2F;1240">
<meta property="og:updated_time" content="2019-11-13T13:27:14.000Z">
<meta name="twitter:card" content="summary">
<meta name="twitter:image" content="http:&#x2F;&#x2F;upload-images.jianshu.io&#x2F;upload_images&#x2F;1323506-23417ce5aa268c69.png?imageMogr2&#x2F;auto-orient&#x2F;strip%7CimageView2&#x2F;2&#x2F;w&#x2F;1240">

<link rel="canonical" href="https://duyang2903.gitee.io/2019/11/15/%E5%A4%A7%E8%AF%9D%E5%AD%98%E5%82%A8%EF%BC%8C%E5%AD%A6%E4%B9%A0%E7%AC%94%E8%AE%B0%EF%BC%8818%E7%AB%A0%EF%BC%89%EF%BC%8C%E6%95%B0%E6%8D%AE%E5%89%8D%E5%A4%84%E7%90%86%E5%92%8C%E5%90%8E%E5%A4%84%E7%90%86/">


<script id="page-configurations">
  // https://hexo.io/docs/variables.html
  CONFIG.page = {
    sidebar: "",
    isHome: false,
    isPost: true,
    isPage: false,
    isArchive: false
  };
</script>

  <title>大话存储，学习笔记（18章），数据前处理和后处理 | dy2903的博客</title>
  






  <noscript>
  <style>
  .use-motion .brand,
  .use-motion .menu-item,
  .sidebar-inner,
  .use-motion .post-block,
  .use-motion .pagination,
  .use-motion .comments,
  .use-motion .post-header,
  .use-motion .post-body,
  .use-motion .collection-header { opacity: initial; }

  .use-motion .site-title,
  .use-motion .site-subtitle {
    opacity: initial;
    top: initial;
  }

  .use-motion .logo-line-before i { left: initial; }
  .use-motion .logo-line-after i { right: initial; }
  </style>
</noscript>

</head>

<body itemscope itemtype="http://schema.org/WebPage">
  <div class="container use-motion">
    <div class="headband"></div>

    <header class="header" itemscope itemtype="http://schema.org/WPHeader">
      <div class="header-inner"><div class="site-brand-container">
  <div class="site-meta">

    <div>
      <a href="/" class="brand" rel="start">
        <span class="logo-line-before"><i></i></span>
        <span class="site-title">dy2903的博客</span>
        <span class="logo-line-after"><i></i></span>
      </a>
    </div>
        <p class="site-subtitle">与肝胆人共事，从无字句读书</p>
  </div>

  <div class="site-nav-toggle">
    <div class="toggle" aria-label="Toggle navigation bar">
      <span class="toggle-line toggle-line-first"></span>
      <span class="toggle-line toggle-line-middle"></span>
      <span class="toggle-line toggle-line-last"></span>
    </div>
  </div>
</div>


<nav class="site-nav">
  
  <ul id="menu" class="menu">
        <li class="menu-item menu-item-home">

    <a href="/" rel="section"><i class="fa fa-fw fa-home"></i>Home</a>

  </li>
        <li class="menu-item menu-item-archives">

    <a href="/archives/" rel="section"><i class="fa fa-fw fa-archive"></i>Archives</a>

  </li>
  </ul>

</nav>
</div>
    </header>

    
  <div class="back-to-top">
    <i class="fa fa-arrow-up"></i>
    <span>0%</span>
  </div>


    <main class="main">
      <div class="main-inner">
        <div class="content-wrap">
          

          <div class="content">
            

  <div class="posts-expand">
      
  
  
  <article itemscope itemtype="http://schema.org/Article" class="post-block " lang="en">
    <link itemprop="mainEntityOfPage" href="https://duyang2903.gitee.io/2019/11/15/%E5%A4%A7%E8%AF%9D%E5%AD%98%E5%82%A8%EF%BC%8C%E5%AD%A6%E4%B9%A0%E7%AC%94%E8%AE%B0%EF%BC%8818%E7%AB%A0%EF%BC%89%EF%BC%8C%E6%95%B0%E6%8D%AE%E5%89%8D%E5%A4%84%E7%90%86%E5%92%8C%E5%90%8E%E5%A4%84%E7%90%86/">

    <span hidden itemprop="author" itemscope itemtype="http://schema.org/Person">
      <meta itemprop="image" content="/images/avatar.gif">
      <meta itemprop="name" content="dy2903">
      <meta itemprop="description" content="">
    </span>

    <span hidden itemprop="publisher" itemscope itemtype="http://schema.org/Organization">
      <meta itemprop="name" content="dy2903的博客">
    </span>
      <header class="post-header">
        <h1 class="post-title" itemprop="name headline">
          大话存储，学习笔记（18章），数据前处理和后处理
        </h1>

        <div class="post-meta">
            <span class="post-meta-item">
              <span class="post-meta-item-icon">
                <i class="fa fa-calendar-o"></i>
              </span>
              <span class="post-meta-item-text">Posted on</span>

              <time title="Created: 2019-11-15 10:48:24" itemprop="dateCreated datePublished" datetime="2019-11-15T10:48:24+08:00">2019-11-15</time>
            </span>
              <span class="post-meta-item">
                <span class="post-meta-item-icon">
                  <i class="fa fa-calendar-check-o"></i>
                </span>
                <span class="post-meta-item-text">Edited on</span>
                <time title="Modified: 2019-11-13 21:27:14" itemprop="dateModified" datetime="2019-11-13T21:27:14+08:00">2019-11-13</time>
              </span>

          

        </div>
      </header>

    
    
    
    <div class="post-body" itemprop="articleBody">

      
        <p>存储其实就是一台主机，上面也运行着各种各样的应用程序，可以在原本的裸数据之上实现更高级的功能，实现更多的附加值。现在的高端存储越来越开发，比如EMC 的 V-MAX，高端存储也用普通的x86了。</p>
<p>存储系统有两大功能：数据存储和数据管理。</p>
<ul>
<li><p>数据存储：控制器、磁盘、HBA卡等，主要是提供<strong>裸数据</strong>存储服务。</p>
</li>
<li><p>数据管理：分层、快照、克隆等高级功能。又可把数据管理部分分为对数据的<strong>前处理和后处理</strong></p>
<ul>
<li><p>前处理：数据未放入磁盘之前的初加工，或者对存放空间做预先准备，比如精简、重删</p>
</li>
<li><p>后处理：数据写入磁盘之后，再将数据读出来进行处理。比如数据迁移。</p>
<p>有些功能既有前处理的过程，又有后处理的过程。比如快照，快照的生成是后处理，但是生产后，每个IO会Copy on Write，这就是典型的前处理。</p>
<p>所以存储除了比主机多运行了一些更强大更复杂的功能之外，其他与主机无异，比如快照、重删、镜像、复制等。</p>
</li>
</ul>
</li>
</ul>
<h1 id="Thin-Provision"><a href="#Thin-Provision" class="headerlink" title="Thin Provision"></a>Thin Provision</h1><h2 id="超供的模式"><a href="#超供的模式" class="headerlink" title="超供的模式"></a>超供的模式</h2><p>精简也即<code>Thin Provision</code>，但是精简这种翻译故弄玄虚，不如叫<code>超供(Over Allocation)</code>最能反映本质。</p>
<p>我们知道申请一个3G的网络硬盘，供应商不会真的提供3GB的空间，它只是记录一下，只有真的塞入了3GB的数据，才会占用这么多空间。</p>
<p>这是怎么办到的？因为不是每个人都会把自己的空间用完，如果前面先把空间分配出去了，又一直没有人占用，空间上就有浪费。这样系统其实可以在后台悄悄的把空间分配给其他的客户端，相当于对客户端进行<strong>欺骗</strong>。</p>
<p>这种方法其实非常常见，比如说在银行存钱10000块，银行不会一直给你保留那么多钱，而是会把钱偷偷的拿来放贷。这是因为不是每个人都会立刻取钱的，完全可以拆东墙补西墙。</p>
<p>总结一下，所谓<code>超供</code>，就是指分配给你的空间是虚的，只有在实际用到的时候才占用空间。所以存储系统需要实时监控物理空间的使用情况，一旦到了临界值，则需要扩容。</p>
<p>要实现超供，NAS系统较容易实现，因为NAS系统是自己维护文件与物理空间的对应关系的。但是如果存储系统提供的是<strong>块</strong>，因为文件与物理空间的映射其实是由更上层的文件系统维护的，存储系统本身是感知不到的。</p>
<p>那么Thin Provision是怎么实现的呢？</p>
<ul>
<li><p>如果存储系统使用文件系统的思想：</p>
<p>  文件系统中有一种<code>稀疏文件，Sparse File</code>，它的作用是在向文件中写入大量的<code>0</code>的时候，实际上只在<strong>内存</strong>上生成这些0，只是在真正需要的时候才分配空间。</p>
<p>  所以只需要对Spare File进行修改，然后把LUN设置为一个Sparse File就可以了。</p>
</li>
<li><p>如果存储系统不是使用文件系统的思想</p>
<p>  我们自然需要单独维护一张<strong>逻辑地址与物理地址的映射表</strong>，可以以连续条带做为单位来进行扩充。</p>
<p>  问题就是随着时间的推移，有可能会出现逻辑上连续的条带但是在物理上却不连续的情况，所以大块连续的IO却变成了随机IO，效率自然低下。</p>
</li>
</ul>
<h2 id="Thin-Provision对性能的影响"><a href="#Thin-Provision对性能的影响" class="headerlink" title="Thin Provision对性能的影响"></a>Thin Provision对性能的影响</h2><p>Thin Provision对性能的影响主要在：耗费额外的CPU周期、物理空间碎片上。</p>
<ul>
<li><p>额外的CPU周期：</p>
<p>  收到一个读IO，需要查Bitmap看读IO的目的地址是否已经分配了空间，如果没分配，则需要返回应全0x00，同样对写IO，则需要查目的地址是否被写过，如果被写过的话，还需要查找其他的空间。多了很多的步骤，而且还需要维护元数据，对计算资源消耗比较大。</p>
</li>
<li><p>物理空间碎片：</p>
<p>  因为Thin是随用随分配，如同操作系统对内存的管理一样，则一定会产生碎片的，不样连续的空间可能被多个LUN占用，活生生的把连续IO变成了随机IO，效率自然降低。</p>
</li>
</ul>
<p>要实现Thin的核心模块，只要有三大元数据就够了：位图、表、树。</p>
<ul>
<li><p>位图：记录底层连续物理空间那些分配了，哪些未被分配。</p>
</li>
<li><p>表：记录LUN逻辑地址与物理地址的对应关系。因为逻辑地址已经不于传统的物理地址一一对应了。这张表需要按照逻辑地址进行排序，以便于查询。</p>
</li>
<li><p>树：在内存中生成，用于迅速的查询表的结构。</p>
</li>
</ul>
<p>比如使用64b的地址长度， 分配粒度32KB，也就是说每32KB的物理块就用一个64b的地址进行表示。因为表代表了逻辑与物理地址的对应关系，所以表的每一项条目大小就是128b。对于100TB来说，对应的表的容量为$(100TB/32KB)*128b=512MB$，如果使用1MB的块粒度，则元数据降为16MB/TB，差别还是很大的。</p>
<p>而且元数据这么大，不可能全部放到内存里面，所以又会牵扯到读写磁盘，性能严重下降。</p>
<h2 id="Thin-Provision脆弱性"><a href="#Thin-Provision脆弱性" class="headerlink" title="Thin Provision脆弱性"></a>Thin Provision脆弱性</h2><ul>
<li><p>对性能影响太大：</p>
<p>  有些厂商的产品，开启了Thin功能，性能降了70%，而粒度与性能总是一对矛盾，为了性能而增加粒度，就会丧失Thin的意义。</p>
<p>  Thin还会引入碎片的问题，所以需要进行碎片整理，与文件系统的碎片整理不同，LUN碎片整理指的是把分配到不同的RAID组上的碎片进行整理，而文件系统碎片整理指的是对LUN内的逻辑上文件碎片进行整理。</p>
</li>
<li><p>效果很难维持：比如说在文件系统再进行了碎片整理，它会读出零散的碎片，合并以后写到新的位置，对Thin LUN来说，又需要重新分配新位置。比如100GB的LUN上有50GB的碎片，现在Thin LUN可能只分配了70GB物理空间，进行<strong>文件系统</strong>碎片整理以后，读出50GB的碎片，发现还需要30GB空间，这样反而把之前没有分配的30GB重新分配掉了。</p>
<p>  再比如有些应用程序会生成大量的临时文件，结束以后就删除了，但是实际上底层LUN无法感知到，而且已经分配出去了，就没法回到原来了。</p>
<p>  综上，Thin Provision其实很脆弱，真的要不反弹的瘦，需要从应用层业务层入手，杜绝垃圾的产生。<br><img src="http://upload-images.jianshu.io/upload_images/1323506-23417ce5aa268c69.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240" alt="image.png"></p>
</li>
</ul>
<h2 id="LUN-Space-Reclaiming"><a href="#LUN-Space-Reclaiming" class="headerlink" title="LUN Space Reclaiming"></a>LUN Space Reclaiming</h2><p>比如存储只有1TB的空间，多个客户端的LUN分布在上面，现在只剩下了500GB，此时如果谁还需要500GB的LUN空间做某程序的TMP空间，则管理员只要把所有空间都给它。但是程序运行完毕以后，临时文件已经删除，但是因为这些空间之前已经分配了，所以无法再次利用。</p>
<p>若通过缩小LUN来解决这个问题，需要消耗太多的资源，那么有其他的方法么？</p>
<ul>
<li><p>存储可以自动识别对应的文件系统，当然就知道那些空间可以回收了，但是实际上目前没有产品进行尝试，因为主机端的文件系统多种多样，就算同一种系统，内核版本不同差别也蛮大的。而且，主机端文件系统是有<strong>缓存</strong>，如果存储端擅自回收空间的话，可能造成数据不一致。</p>
</li>
<li><p>存储系统自动识别0x00然后删除他们：</p>
<p>  文件系统在删除文件的时候，只是把文件从元数据中抹掉，如果再加一步，将占用的Block写入0x00的话，那么存储系统可以定期扫描LUN，发现大片连续的0x00，则回收空间。这种技术叫<code>Zero Detection</code>。缺点是，每次删除文件的时候，都需要写入大量的0进行战场的清扫，耗费的资源是极不划算的。</p>
<p>  不过这种方法在特定的场景比较有用，比如VMware在新建虚拟机的时候，需要大量写0，先把空间占住，这样做的目的是看看存储系统能提供的空间是否够用。所以可以使用这种<code>Zero Detection</code>把连续的0x00的空间回收掉。再比如Oracle数据库也有大片大片的0x00，通过这种方式也可以节省空间。</p>
</li>
<li><p>主机端通过API通知存储系统。</p>
<p>  在主机端运行一个代理程序，定期扫描剩余空间并将对应信息返回存储控制器。类似与SSD的Trim技术，几乎所有的SSD厂商都有空间回收专用程序。</p>
</li>
</ul>
<p><img src="http://upload-images.jianshu.io/upload_images/1323506-bcc64eec94fa3921.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240" alt="image.png"></p>
<h1 id="分级"><a href="#分级" class="headerlink" title="分级"></a>分级</h1><h2 id="分层存储管理的意义"><a href="#分层存储管理的意义" class="headerlink" title="分层存储管理的意义"></a>分层存储管理的意义</h2><p><img src="http://upload-images.jianshu.io/upload_images/1323506-9efd2a107ec96778.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240" alt="image.png"></p>
<p>我们知道对存储介质而言，性能与价格是不可兼得的。上图就表现得很明显，对于Cache ，RAM速度快，但是价格高，而且是易失的，也就是一掉电啥就没有了。</p>
<p>存储介质到了磁盘这一层，又到了个质变点，磁盘之下的虚拟磁带库、磁带都是不可随机访问的，只能当做离线存储来用。而虚拟磁带库之所以称为<strong>近线存储</strong>，是因为从在线存储将数据迁移到离线存储之后，一旦短时间内需要再次访问，需要忍受非常低的速度，而虚拟磁带库可以把数据快速提取出来，<strong>虽然仍然不可以随机存取而已。</strong></p>
<p>所以数据分级意义在于，将<strong>访问频繁、性能要求高的数据</strong>放在性能高的磁盘或者RAID组里面，不经常访问的数据移到低端硬盘里面去。这样就可以物尽其用。</p>
<p><img src="http://upload-images.jianshu.io/upload_images/1323506-29bc778c574a6338.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240" alt="image.png"></p>
<h2 id="数据分级的具体形式"><a href="#数据分级的具体形式" class="headerlink" title="数据分级的具体形式"></a>数据分级的具体形式</h2><ul>
<li><p>手动、自动、实时自动分级</p>
<p>  顾名思义，手动分级需要用户自行迁移数据，而自动分级很大程度代理了用户本身，只需要提前设置<strong>规则</strong>，由分级引擎扫描元数据，一旦符合条件，则触发迁移任务。</p>
<p>  实时自动分级指的是数据写入的时候，分级引擎实时将数据重定向到对应目标。</p>
</li>
<li><p>文件级分级和块级分级</p>
<p>  文件级分级可以做到更细化策略，比如可以根据扩展名、访问频率等属性来进行分类。而且数据迁移到其他的Tier以后，原始的Tier上需要保持一个指针，目的是不影响用户的使用，因为用户程序是不会感知道文件实体放在哪里，它只需要知道文件的<strong>路径</strong>就可以了。</p>
<p>  基于块级别的数据分级所能使用的触发条件就少很多了，比如根据整个LUN或者某些Block的访问频度来进行迁移，因为块级别无法感知道上层文件逻辑。</p>
</li>
<li><p>主机端分级和存储端分级</p>
<p>  主机可以同时连接到多个外部存储上，所以如果在主机上分级可以实现数据在不同的外部存储上迁移。一般来说，需要在主机端上安装<code>代理软件</code>来监视和管理。</p>
<p>  存储系统的数据分级只能将数据在自身不同的Tier上迁移， 是完全对主机端透明的。</p>
</li>
<li><p>应用级分级和底层级分级</p>
<p>  针对于应用系统，比如数据库软件催生了专门的数据管理工具，比如对数据进行容灾、分级迁移。</p>
<p>  运行在主机端的数据分级管理程序则以普适为原则，针对任何文件、LUN进行迁移。</p>
</li>
</ul>
<p><img src="http://upload-images.jianshu.io/upload_images/1323506-b64d1f5a73ea0c04.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240" alt="image.png"></p>
<h2 id="怎么判断热点数据"><a href="#怎么判断热点数据" class="headerlink" title="怎么判断热点数据"></a>怎么判断热点数据</h2><p>一般利用<strong>二八原则</strong>，把数据按照单位时间内被IO次数来进行排序，访问次数最多的20%数据为<strong>热数据</strong></p>
<h2 id="块级自动分级的底层数据结构"><a href="#块级自动分级的底层数据结构" class="headerlink" title="块级自动分级的底层数据结构"></a>块级自动分级的底层数据结构</h2><p>自动分级存储一般需要追踪每个块的<strong>属性</strong>，比如最后访问时间、某段时间内访问了多少次等数据。保存的这些数据有两种方法：</p>
<ul>
<li><p>每个块里的首或者尾追加部分空间来存放这些元数据，这就是<strong>带内元数据法</strong></p>
</li>
<li><p>单独构建一个小型数据库来存放所有块的元数据，这个数据库的数据存放在一个单独的空间，这就是<strong>带外元数据法</strong></p>
<p>  对于<strong>带内元数据法</strong>，系统即使是读，也会更新元数据块，而且分布在磁盘各处，性能问题严重。一个解决方法是使用<strong>日志</strong>，将要更新的东西记录在日志里面，在不繁忙的时候进行重放，这种方法注定要频繁的IO操作，极其浪费资源。</p>
<p>  <strong>带外元数据法</strong>更符合常理，不需要对数据块做任何结构改变，可以使用独立的软件模式来交付。</p>
</li>
</ul>
<p>集群、分布式文件系统天生就是自动分级的坯子，因为本来一个文件或者一个LUN的不同部分就可以放到不同的位置上，只需要在上面进行一些开发就可以很容易的实现分级。</p>
<h2 id="对性能的影响"><a href="#对性能的影响" class="headerlink" title="对性能的影响"></a>对性能的影响</h2><p>与 Thin Provision一样，分块粒度越小，性能损失越大。</p>
<ul>
<li><p>分块越小，元数据量大量增加，搜索和处理效率降低。</p>
</li>
<li><p>而且分级之后的数据块在物理上不连续了，增加了寻道操作，降低了性能。</p>
</li>
</ul>
<p><img src="http://upload-images.jianshu.io/upload_images/1323506-ad949c38a020a603.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240" alt="image.png"></p>
<h1 id="Deduplication（重删）"><a href="#Deduplication（重删）" class="headerlink" title="Deduplication（重删）"></a>Deduplication（重删）</h1><p>不同机器的本地存储里面有若干文件，如果这些文件存在重复，每次备份自然有很多的相同部分，比较浪费空间，有没有办法来解决：</p>
<p>在开始讲解决方法之前，我们可以先总结一下出现重复可能的场景：</p>
<ul>
<li><p>同一主机或者不同主机的本地存储的重复文件</p>
</li>
<li><p>不同主机在同一NAS或者同一块存储上的重复文件</p>
</li>
<li><p>虚拟机磁盘镜像文件的重复部分</p>
</li>
<li><p>虚拟机下裸磁盘映射模式的重复部分<br><img src="http://upload-images.jianshu.io/upload_images/1323506-040f7a2cbccea364.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240" alt="image.png"></p>
<h2 id="SIS的缺陷"><a href="#SIS的缺陷" class="headerlink" title="SIS的缺陷"></a>SIS的缺陷</h2><p>传统的解决方案是<strong>Single Instance Storage（SIS，单一实例存储）</strong>，可以相同内容的<strong>文件</strong>在系统中只存在一份实体，其他副本只作为指针链接而存在。注意这种技术只能避免相同内容的文件，所以只能解决同一主机里的重复文件以及连接多主机的NAS设备上的重复文件。</p>
</li>
</ul>
<p>但是对于多台主机连接到同一块存储这种场景，因为块存储对每一台主机提供不同的LUN，所以就类似于不同主机的本地存储有重复文件一样，所以依然是无能为力的。</p>
<p>我们知道虚拟机的镜像其实就是一堆文件而已，但是这些文件不大可能在每个字节上都相同，即使是安装的同一种操作系统，但是安装的应用当然是不同的。所以SIS对这种场景也无能为力。</p>
<p>最后一种情况，根本看不到文件，当然也不能实现重删。</p>
<p>SIS可以理解为<strong>文件级别的重删</strong>，不能解决所有场景的问题。而且在底层实现上也有极大的局限性，比如只能以整个文件作为对比，对于那种大部分相同但是有细微差别的文件就没办法处理了。</p>
<p>所以<strong>块级别的重删</strong>才是有意义的。可以直接比对Block的内容，消除多个副本，在元数据中只留一个<strong>指针</strong>来指向唯一一份实体即可。</p>
<p>dedup与压缩有什么区别？压缩只是局部上进行处理，而Dedup可以实现全局数据的重删。</p>
<p><img src="http://upload-images.jianshu.io/upload_images/1323506-f1f66c109e142cf8.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240" alt="image.png"></p>
<h2 id="核心技术——HASH"><a href="#核心技术——HASH" class="headerlink" title="核心技术——HASH"></a>核心技术——HASH</h2><p>重删用到的关键技术就是HASH算法。在<a href="https://www.cnblogs.com/dy2903/p/8426859.html" target="_blank" rel="noopener">数据库（三），底层算法</a>中我们已经说了Hash算法之神奇。下面再简单的介绍一下它的应用场景。</p>
<p>我们知道每个人的指纹各不相同，于是可以通过比对指纹就可以确定是否是同一个人留下的。同理，如果给每个Block录一个指纹，就可以快速比对出这两个块是否是完全一样呢。</p>
<p>那么生成数据指纹的有一种很好的算法，就是<strong>HASH</strong>。它又衍生出MD5(Message Digest v5)和SHA-1(Secure Hash Algorithm v1)。</p>
<p>这些算法的特点在于</p>
<ul>
<li><p>不管数据有多长，只要不超过额定大小，经过计算以后，一定可以得到一个<strong>固定</strong>长度值，比如SHA-1对一段小于264的数据进行计算以后，可以得到一个长度为160的值。</p>
</li>
<li><p>同时相同的数据经过HASH以后，总会得到相同的<strong>指纹</strong>。</p>
</li>
<li><p>而且这种HASH方法是<strong>不可逆</strong>的，也就是说通过指纹不能算出原来的值是多少。</p>
</li>
</ul>
<p>HASH算法有很多的应用。</p>
<ul>
<li><p>应用一：因为HASH以后的值不能被逆算出，所以我们完全可以将其用于登录密码保存上，这样即使黑客将密码HASH以后的值拦截到了，依然无法逆算出原来的密码。</p>
<p>  那么你可能要问，用户正常登录的时候如何匹配呢？这个时候，只要我们在后端的数据库里面依然存放密码的HASH以后的值即可，只要密码HASH以后的值与数据库中存放的对应内容匹配，则认证成功。</p>
</li>
<li><p>应用二：还有就是<strong>听歌识曲</strong>的功能，比如录制的一段曲子传到服务器上，服务器就可以告诉你这段曲子的名称。实际也就是根据曲子的音调生成指纹，然后于数据库大量的标本进行匹配，发现类似的歌曲返回名称即可。</p>
</li>
<li><p>应用三：判断数据传输的时候是否在内容上发生了改变。只要在源端算一个指纹，目的端再算一次，对比两个指纹是否一致即可知道是否改变。</p>
</li>
<li><p>应用四：远端Cache。某个CDN内容发布在网络环境中，针对一份源数据，在各地拥有多个二级Cache。这些Cache需要严格保证一致性，如果源发生了改变，指纹当然也改变了。那么可以随时拉取源端的指纹进行对比，发现不匹配则此Cache不再可用。</p>
</li>
<li><p>应用五：数字签名。将某人给出的一串特定字符转换成指纹。</p>
</li>
</ul>
<p><img src="http://upload-images.jianshu.io/upload_images/1323506-6f143cb79e866a4d.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240" alt="image.png"></p>
<h2 id="HASH冲突"><a href="#HASH冲突" class="headerlink" title="HASH冲突"></a>HASH冲突</h2><p>要完全杜绝Hash冲突的唯一办法就是当对比两个HASH值的之后发现二者匹配以后，可以再进行<strong>逐位对比</strong>，或者取相同的部分进行对比。</p>
<p>但是这样做的话会耗费大量的计算和IO资源，我们可以换一种思路，取<strong>两种HASH算法进行计算</strong>，如果两次都比对都相同，则可以认为是重复的。</p>
<h2 id="主机Dedup的过程"><a href="#主机Dedup的过程" class="headerlink" title="主机Dedup的过程"></a>主机Dedup的过程</h2><p>Dedup主要包含如下4个动作，注意这里面的Dedup软件是安装在主机上的。<br><img src="http://upload-images.jianshu.io/upload_images/1323506-b26816b8afd22491.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240" alt="image.png"></p>
<ul>
<li><p>主机的Filter Driver实时监测写IO，透传到下层，同时复制一份到Dedup主模块。</p>
<p>  Dedup主模块将写IO Hash以后，存到指纹仓库里面，对Delay Block Bitmap置0。这个Bitmap是干嘛的？如果因为CPU负载过高等原因，Dedup引擎暂停工作，则这个写IO会被计算成Hash值存放，我们可以用一个bitmap来记录这写IO的位置，后续再进行计算。</p>
</li>
<li><p>Dedup主模块会在<strong>后台</strong>查找与指纹库里面重合的指纹，对于查找的菜块，会生成一个<strong>指针</strong>，并且保存在On Disk Pointer List中。这个动作是有Block Mapping Metadata Handler完成的，这个过程是真正的数据消重的过程。</p>
</li>
<li><p>针对Bitmap里面记录的暂未计算HASH的部分，还会在空闲的时刻完成后续的操作，并且把Bitmap的对应位置置回0</p>
</li>
</ul>
<p>这里面需要注意的是每个<strong>写IO</strong>都会写入存储介质中。那么大家肯定有疑问了，既然每个写IO都落到磁盘上，何来消重。</p>
<p>其实这个问题之前已经讨论了很多次了。谁来决定LUN的剩余空间，当然是上层文件。所以如果我们要想让主机端的Dedup有意义，只能</p>
<ul>
<li><p>让主机端文件系统感知到变化：这对块级Dedup来说是行不通的，因为块级Dedup的实现原理没有考虑到FS层的逻辑</p>
</li>
<li><p>模仿主机端对LUN的管理：可以在LUN上建立一层<strong>卷管理层</strong>，这样卷管理层会感知到哪些卷占用了多少物理空间。</p>
</li>
</ul>
<p>虽然运行在主机端、块级的Dedup，无法达到节省底层存储空间的目的。但是在<strong>备份</strong>的时候就非常有意义了，因为可以减少网络传输的量。</p>
<p>其实根本不用这么纠结，我们完全可以把块级Dedup安装在<strong>存储端</strong>，因为我们最终要节省的就是磁盘空间，而磁盘又是由存储设备管理的<br><img src="http://upload-images.jianshu.io/upload_images/1323506-2177aaa5e479ffec.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240" alt="image.png"></p>
<h2 id="网络数据备份的Dedup"><a href="#网络数据备份的Dedup" class="headerlink" title="网络数据备份的Dedup"></a>网络数据备份的Dedup</h2><p>上面说过主机上的Dedup对备份是有意义的，我们可以传输更少的数据。不过这要求Dedup引擎与备份系统紧密配合，一般来说是作为备份软件的一个<strong>子模块</strong>。</p>
<p>这样做有个不好的地方，也就是会消耗主机的性能。我们也可以在主机后面进行Dedup，比如在介质服务器上，可以使用<strong>前台Dedup</strong>或者<strong>后台Dedup</strong></p>
<ul>
<li><p>如果备份介质是磁带，则必须以前台的方式来进行，因为磁带不可随机访问。</p>
<p>  前台Dedup可以采用<strong>局部和全局</strong>两种模式。区别在于对收到的数据是否还需要与<strong>之前备份过的数据</strong>进行对比。</p>
<ul>
<li><p>局部模式：Dedup引擎对收到的数据实时分割为Block然后计算HASH，并存放在指纹仓库里面。</p>
</li>
<li><p>全局模式：对接收来的数据计算HASH值以后，会将这个HASH值与之前曾备份过的数据的HASH值进行对比。</p>
<p>介质服务器都有本地硬盘，可以将要备份的数据流暂存在本次硬盘某处作为缓冲，然后由Dedup引擎在后台处理，最后写入磁带，这就是<code>D2D2T</code>。</p>
</li>
</ul>
</li>
<li><p>后台Dedup：如果备份介质是虚拟磁带库VTL，则可以使用这种方法。</p>
<p>  介质服务器首先将收的数据流直接写到磁盘中，当引擎触发之后，再从对应目标将数据读出并进行Dedup处理，最后写入介质空间，原有备份数据集删除。<br><img src="http://upload-images.jianshu.io/upload_images/1323506-f874996a7aa24c5c.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240" alt="image.png"></p>
</li>
</ul>
<h2 id="Dedup思想的其他应用"><a href="#Dedup思想的其他应用" class="headerlink" title="Dedup思想的其他应用"></a>Dedup思想的其他应用</h2><p>增量备份、差量备份通常是在<strong>应用程序层</strong>来控制的，因为主要是由应用程序来负责记录备份的时间点以及文件的变化，此时备份软件主要是辅助作用。</p>
<p>然而备份软件自身如何实现LUN级别的增量和差量备份呢？</p>
<ul>
<li><p>差量备份：记录底层Block变化，将上一次备份之后，所发生的所有写对应的Block记录在bitmap中。这样就知道那些是需要再备份的。</p>
</li>
<li><p>增量备份：可以将上一层的Bitmap封存，新建一份空的Bitmap保存上一次<strong>差量或增量备份</strong>LUN的变化。当再次触发备份的时候，将Bitmap中置1的块备份下来，然后封存Bitmap，创建新的Bitmap。恢复的时候，可以根据需要恢复的<strong>备份点</strong>，将所有的Bitmap做一个OR操作，合成一份完整的Bitmap。然后将初次全备份的数据覆盖到目标上。这样就可以根据完整的Bitmap和每次增量备份的Block集提取对应的Block进行备份。</p>
</li>
</ul>

    </div>

    
    
    

      <footer class="post-footer">

        

          <div class="post-nav">
            <div class="post-nav-next post-nav-item">
                <a href="/2019/11/15/%E5%A4%A7%E8%AF%9D%E5%AD%98%E5%82%A8%EF%BC%8C%E5%AD%A6%E4%B9%A0%E7%AC%94%E8%AE%B0%EF%BC%8817%E7%AB%A0%EF%BC%89%EF%BC%8C%E6%95%B0%E6%8D%AE%E5%AE%B9%E7%81%BE/" rel="next" title="大话存储，学习笔记（17章），数据容灾">
                  <i class="fa fa-chevron-left"></i> 大话存储，学习笔记（17章），数据容灾
                </a>
            </div>

            <span class="post-nav-divider"></span>

            <div class="post-nav-prev post-nav-item">
                <a href="/2019/11/15/%E5%A4%A7%E8%AF%9D%E5%AD%98%E5%82%A8%EF%BC%8C%E5%AD%A6%E4%B9%A0%E7%AC%94%E8%AE%B0%EF%BC%8820%E7%AB%A0%EF%BC%89%EF%BC%8C%E4%BA%91%E5%AD%98%E5%82%A8/" rel="prev" title="大话存储，学习笔记（20章），云存储">
                  大话存储，学习笔记（20章），云存储 <i class="fa fa-chevron-right"></i>
                </a>
            </div>
          </div>
      </footer>
    
  </article>
  
  
  

  </div>


          </div>
          

        </div>
          
  
  <div class="toggle sidebar-toggle">
    <span class="toggle-line toggle-line-first"></span>
    <span class="toggle-line toggle-line-middle"></span>
    <span class="toggle-line toggle-line-last"></span>
  </div>

  <aside class="sidebar">
    <div class="sidebar-inner">

      <ul class="sidebar-nav motion-element">
        <li class="sidebar-nav-toc">
          Table of Contents
        </li>
        <li class="sidebar-nav-overview">
          Overview
        </li>
      </ul>

      <!--noindex-->
      <div class="post-toc-wrap sidebar-panel">
          <div class="post-toc motion-element"><ol class="nav"><li class="nav-item nav-level-1"><a class="nav-link" href="#Thin-Provision"><span class="nav-number">1.</span> <span class="nav-text">Thin Provision</span></a><ol class="nav-child"><li class="nav-item nav-level-2"><a class="nav-link" href="#超供的模式"><span class="nav-number">1.1.</span> <span class="nav-text">超供的模式</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#Thin-Provision对性能的影响"><span class="nav-number">1.2.</span> <span class="nav-text">Thin Provision对性能的影响</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#Thin-Provision脆弱性"><span class="nav-number">1.3.</span> <span class="nav-text">Thin Provision脆弱性</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#LUN-Space-Reclaiming"><span class="nav-number">1.4.</span> <span class="nav-text">LUN Space Reclaiming</span></a></li></ol></li><li class="nav-item nav-level-1"><a class="nav-link" href="#分级"><span class="nav-number">2.</span> <span class="nav-text">分级</span></a><ol class="nav-child"><li class="nav-item nav-level-2"><a class="nav-link" href="#分层存储管理的意义"><span class="nav-number">2.1.</span> <span class="nav-text">分层存储管理的意义</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#数据分级的具体形式"><span class="nav-number">2.2.</span> <span class="nav-text">数据分级的具体形式</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#怎么判断热点数据"><span class="nav-number">2.3.</span> <span class="nav-text">怎么判断热点数据</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#块级自动分级的底层数据结构"><span class="nav-number">2.4.</span> <span class="nav-text">块级自动分级的底层数据结构</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#对性能的影响"><span class="nav-number">2.5.</span> <span class="nav-text">对性能的影响</span></a></li></ol></li><li class="nav-item nav-level-1"><a class="nav-link" href="#Deduplication（重删）"><span class="nav-number">3.</span> <span class="nav-text">Deduplication（重删）</span></a><ol class="nav-child"><li class="nav-item nav-level-2"><a class="nav-link" href="#SIS的缺陷"><span class="nav-number">3.1.</span> <span class="nav-text">SIS的缺陷</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#核心技术——HASH"><span class="nav-number">3.2.</span> <span class="nav-text">核心技术——HASH</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#HASH冲突"><span class="nav-number">3.3.</span> <span class="nav-text">HASH冲突</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#主机Dedup的过程"><span class="nav-number">3.4.</span> <span class="nav-text">主机Dedup的过程</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#网络数据备份的Dedup"><span class="nav-number">3.5.</span> <span class="nav-text">网络数据备份的Dedup</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#Dedup思想的其他应用"><span class="nav-number">3.6.</span> <span class="nav-text">Dedup思想的其他应用</span></a></li></ol></li></ol></div>
      </div>
      <!--/noindex-->

      <div class="site-overview-wrap sidebar-panel">
        <div class="site-author motion-element" itemprop="author" itemscope itemtype="http://schema.org/Person">
  <p class="site-author-name" itemprop="name">dy2903</p>
  <div class="site-description" itemprop="description"></div>
</div>
<div class="site-state-wrap motion-element">
  <nav class="site-state">
      <div class="site-state-item site-state-posts">
          <a href="/archives/">
        
          <span class="site-state-item-count">20</span>
          <span class="site-state-item-name">posts</span>
        </a>
      </div>
      <div class="site-state-item site-state-tags">
        <span class="site-state-item-count">2</span>
        <span class="site-state-item-name">tags</span>
      </div>
  </nav>
</div>
  <div class="feed-link motion-element">
    <a href="/atom.xml" rel="alternate">
      <i class="fa fa-rss"></i>RSS
    </a>
  </div>



      </div>

    </div>
  </aside>
  <div id="sidebar-dimmer"></div>


      </div>
    </main>

    <footer class="footer">
      <div class="footer-inner">
        

<div class="copyright">
  
  &copy; 
  <span itemprop="copyrightYear">2019</span>
  <span class="with-love">
    <i class="fa fa-user"></i>
  </span>
  <span class="author" itemprop="copyrightHolder">dy2903</span>
</div>
  <div class="powered-by">Powered by <a href="https://hexo.io/" class="theme-link" rel="noopener" target="_blank">Hexo</a> v4.0.0
  </div>
  <span class="post-meta-divider">|</span>
  <div class="theme-info">Theme – <a href="https://pisces.theme-next.org/" class="theme-link" rel="noopener" target="_blank">NexT.Pisces</a> v7.5.0
  </div>

        












        
      </div>
    </footer>
  </div>

  
  <script src="/lib/anime.min.js"></script>
  <script src="/lib/velocity/velocity.min.js"></script>
  <script src="/lib/velocity/velocity.ui.min.js"></script>
<script src="/js/utils.js"></script><script src="/js/motion.js"></script>
<script src="/js/schemes/pisces.js"></script>
<script src="/js/next-boot.js"></script>



  
















  

  

</body>
</html>
